﻿<documents created="2010-12-15 11:38:12Z"><document src="C:\Users\Anders\Documents\automatones\Visual Studio\AutomaTones\AutomaTones\HW Sense Compute\ComputeLaunchpad.cs" renderPrefix="s0"><chunk hits="-1" domain="unknown"><source><![CDATA[using System;
using AutomaTones.Model.Automaton_Model;
using Midi;
using Microsoft.Pex.Framework;

namespace AutomaTones.HW_Sense_Compute {

    /// <summary>
    /// Computation on inputs from the Launchpad. Part of the Hardware, Sense, Compute pattern.
    /// </summary>
    /// <author>Anders Bech Mellson, anbh@itu.dk</author>
    [PexClass]
    partial class ComputeLaunchpad : ICompute
    {
        private int _x, _y;
        private readonly State _state = new State();
        private bool _settingState, _pushed, _inputGrid, _controlButtonPressed;
        public Action<int,int> LaunchpadEvent;
        public Action<bool> StateButtonEvent;
        public Action<State> StateChangeEvent;
        public Action OkButtonEvent,ClearButtonEvent;

        /// <summary>
        /// Looks at the incoming NoteOnMessage and computes what to do with it.
        /// </summary>
        /// <param name="mMsg"></param>
        [PexMethod]
        public void Compute(NoteOnMessage mMsg) ]]></source>
</chunk>
<method name="Compute" namespace="AutomaTones.HW_Sense_Compute" type="AutomaTones.HW_Sense_Compute.ComputeLaunchpad" typeName="ComputeLaunchpad" token="6000154" module="AutomaTones.exe"><hits><hit index="0" value="1"/>
<hit index="1" value="1"/>
<hit index="48" value="1"/>
</hits>
<coverage domain="userortestcode" unit="block" covered="1" total="17" coveredRatio="0.058823529411764705"/>
</method>
<chunk hits="1" offset="0000" domain="userortestcode"><source><![CDATA[{]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
            ]]></source>
</chunk>
<chunk hits="1" offset="0001" domain="userortestcode"><source><![CDATA[EvaluateNoteOnMessage(mMsg);]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
            // Is the pad being released
            ]]></source>
</chunk>
<chunk hits="0" offset="0009" domain="userortestcode"><source><![CDATA[if (!_pushed)]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
            ]]></source>
</chunk>
<chunk hits="0" offset="0013" domain="userortestcode"><source><![CDATA[{]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                // Is it a statechange button thats being released
                ]]></source>
</chunk>
<chunk hits="0" offset="0014" domain="userortestcode"><source><![CDATA[if (!_inputGrid)]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[ ]]></source>
</chunk>
<chunk hits="0" offset="001e" domain="userortestcode"><source><![CDATA[{]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                    ]]></source>
</chunk>
<chunk hits="0" offset="001f" domain="userortestcode"><source><![CDATA[StateButtonEvent(false);]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                    ]]></source>
</chunk>
<chunk hits="0" offset="002c" domain="userortestcode"><source><![CDATA[_settingState = false;]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                ]]></source>
</chunk>
<chunk hits="0" offset="0033" domain="userortestcode"><source><![CDATA[}]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                ]]></source>
</chunk>
<chunk hits="0" offset="0034" domain="userortestcode"><source><![CDATA[return;]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
            }
            // Is the pad a statechange pad
            ]]></source>
</chunk>
<chunk hits="0" offset="0036" domain="userortestcode"><source><![CDATA[if (!_inputGrid)]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[ ]]></source>
</chunk>
<chunk hits="0" offset="0040" domain="userortestcode"><source><![CDATA[{]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                // Is a statechange pad already being pushed
                ]]></source>
</chunk>
<chunk hits="0" offset="0041" domain="userortestcode"><source><![CDATA[if (_settingState)]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                    ]]></source>
</chunk>
<chunk hits="0" offset="004e" domain="userortestcode"><source><![CDATA[return;]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                ]]></source>
</chunk>
<chunk hits="0" offset="0050" domain="userortestcode"><source><![CDATA[SetState(mMsg.Pitch);]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                ]]></source>
</chunk>
<chunk hits="0" offset="005d" domain="userortestcode"><source><![CDATA[StateButtonEvent(true);]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                ]]></source>
</chunk>
<chunk hits="0" offset="006a" domain="userortestcode"><source><![CDATA[_settingState = true;]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
            ]]></source>
</chunk>
<chunk hits="0" offset="0071" domain="userortestcode"><source><![CDATA[}]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                // Is the pad a valid pad within the 8x8 inputgrid
            else ]]></source>
</chunk>
<chunk hits="0" offset="0074" domain="userortestcode"><source><![CDATA[{]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                ]]></source>
</chunk>
<chunk hits="0" offset="0075" domain="userortestcode"><source><![CDATA[SetXandYfromPitch(mMsg.Pitch);]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                ]]></source>
</chunk>
<chunk hits="0" offset="0082" domain="userortestcode"><source><![CDATA[LaunchpadEvent(_x,_y);]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
            ]]></source>
</chunk>
<chunk hits="0" offset="009a" domain="userortestcode"><source><![CDATA[}]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
        ]]></source>
</chunk>
<chunk hits="0" offset="009b" domain="userortestcode"><source><![CDATA[}]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[

        /// <summary>
        /// Checks the incoming NoteOnMessage and sets the relevant booleans according to the input.
        /// </summary>
        private void EvaluateNoteOnMessage(NoteOnMessage noteMsg)
        ]]></source>
</chunk>
<method name="EvaluateNoteOnMessage" namespace="AutomaTones.HW_Sense_Compute" type="AutomaTones.HW_Sense_Compute.ComputeLaunchpad" typeName="ComputeLaunchpad" token="6000155" module="AutomaTones.exe"><hits><hit index="0" value="1"/>
<hit index="1" value="1"/>
<hit index="33" value="1"/>
</hits>
<coverage domain="userortestcode" unit="block" covered="1" total="14" coveredRatio="0.071428571428571425"/>
</method>
<chunk hits="1" offset="0000" domain="userortestcode"><source><![CDATA[{]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
            ]]></source>
</chunk>
<chunk hits="1" offset="0001" domain="userortestcode"><source><![CDATA[switch (noteMsg.Velocity)]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
            {
                // Pad is pushed down on the Launchpad
                case 127:
                    ]]></source>
</chunk>
<chunk hits="0" offset="0013" domain="userortestcode"><source><![CDATA[_pushed = true;]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                    ]]></source>
</chunk>
<chunk hits="0" offset="001a" domain="userortestcode"><source><![CDATA[break;]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                // Pad is being released on the Launchpad
                case 0:
                    ]]></source>
</chunk>
<chunk hits="0" offset="001c" domain="userortestcode"><source><![CDATA[_pushed = false;]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                    ]]></source>
</chunk>
<chunk hits="0" offset="0023" domain="userortestcode"><source><![CDATA[break;]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
            }
            // Pad is in the square 8x8 grid on the Launchpad
            ]]></source>
</chunk>
<chunk hits="0" offset="0025" domain="userortestcode"><source><![CDATA[if (ValidPad(noteMsg.Pitch))]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                ]]></source>
</chunk>
<chunk hits="0" offset="0037" domain="userortestcode"><source><![CDATA[_inputGrid = true;]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
            // Pad is one of the round state change pad's on the right side of the Launchpad
            else ]]></source>
</chunk>
<chunk hits="0" offset="0040" domain="userortestcode"><source><![CDATA[if (!ValidPad(noteMsg.Pitch))]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
                ]]></source>
</chunk>
<chunk hits="0" offset="004f" domain="userortestcode"><source><![CDATA[_inputGrid = false;]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[
        ]]></source>
</chunk>
<chunk hits="0" offset="0056" domain="userortestcode"><source><![CDATA[}]]></source>
</chunk>
<chunk hits="-1" domain="unknown"><source><![CDATA[

        /// <summary>
        /// If one of the toprow buttons are pushed it sends events based on the correct button.
        /// </summary>
        [PexMethod]
        public void ControlButton(ControlChangeMessage cMsg) {
            _controlButtonPressed = !_controlButtonPressed;
            if (_controlButtonPressed)
                switch ((int)cMsg.Control) {
                    case 104:
                        OkButtonEvent();
                        break;
                    case 111:
                        ClearButtonEvent();
                        break;
                }
        }

        /// <summary>
        /// Takes a Pitch and sets the global values of x & y in this class.
        /// The incoming pitch messages are in the range 1-120, some modulo math converts these incoming messages to x & y.
        /// Row one sends: 0-7, Row two sends 16-23, Row three: 32-39, Row four: 48-55, Row five: 64-71, Row six: 80-87, Row seven: 96-103, Row eight: 112-119.
        /// </summary>
        /// <param name="pitch">A Pitch message from an incoming MIDI message.</param>
        private void SetXandYfromPitch(Pitch pitch) {
            int point = (int)pitch;
            _x = (point % 8);
            _y = (point - _x) / 16;
        }

        /// <summary>
        /// Checks if the incoming pitch if within the valid range. Eg if the button press is within the 8x8 field of buttons.
        /// </summary>
        /// <param name="pitch"></param>
        /// <returns></returns>
        private static bool ValidPad(Pitch pitch) {
            int p = (int)pitch;
            if (p > 7 && p < 16 || p > 23 && p < 32 || p > 39 && p < 48 || p > 55 && p < 64 || p > 71 && p < 80 || p > 87 && p < 96 || p > 103 && p < 112 || p > 119)
                return false;
            return true;
        }

        /// <summary>
        /// If the NoteOn message is not in the 8x8 button field, then sets the state according to the button pressed.
        /// </summary>
        /// <param name="pitch"></param>
        private void SetState(Pitch pitch) {
            switch ((int) pitch) {
                case 8:
                    _state.CurrentState = 0;
                    break;
                case 24:
                    _state.CurrentState = 1;
                    break;
                case 40:
                    _state.CurrentState = 2;
                    break;
                case 56:
                    _state.CurrentState = 3;
                    break;
                case 72:
                    _state.CurrentState = 4;
                    break;
                case 88:
                    _state.CurrentState = 5;
                    break;
                case 104:
                    _state.CurrentState = 6;
                    break;
                case 120:
                    _state.CurrentState = 7;
                    break;
            }
            StateChangeEvent(_state);
        }
    }
}
]]></source>
</chunk>
</document>
<document src="(no sources available for some parts of Midi.Explorables)" missing="true"><method name="Create" type="Midi.NoteOnMessageFactory" token="6000002" module="&lt;In Memory Module&gt;"><hits/>
<coverage domain="userortestcode" unit="block" covered="0" total="2" coveredRatio="0"/>
</method>
</document>
</documents>
